#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

#include "include.h"
#include "HelperUtils.h"
#include "SerialIO.h"
#include "UInput.h"

int main(int argc, char** argv) {
    pid_t serialIOPid, uInputPid;
    // Command buffer to hold QUIT
    char *command = NULL;
    size_t commandSize = 0;

    // Create a data pipe to talk to serial IO process
    int serialIOPipe[2];
    if (pipe(serialIOPipe)==-1) {
    	dieWithError("FATAL: pipe() failed.");
    }

    // Setup SIGINT handler to disable ctrl+c and prevent zombie child
    struct sigaction newAction;
    newAction.sa_handler = SIG_IGN;
    sigemptyset(&newAction.sa_mask);
    newAction.sa_flags = 0;
    if ( sigaction (SIGINT, &newAction, NULL) == -1 ) {
    	dieWithError("FATAL: signal() failed.");
    }

    // Fork out child process to handle serial IO
    switch(serialIOPid = fork()) {
    case -1:
        dieWithError("FATAL: fork() failed.");
    case 0:		
        // Child process to handle serial IO
    	// Pass commandPipe to child
        serialIOMain(serialIOPipe);
        exit(1);
    default:	
    	// Parent process
    	// Fork another child to drive uinput
    	switch(uInputPid = fork()){
        case -1:
            dieWithError("FATAL: fork() failed.");
        case 0:
            // Child process to handle UInput
            uInputMain(serialIOPid, serialIOPipe);
            exit(1);
        default:
            // This is parent
            while (1) {
                command = NULL;
                commandSize = 0;
                getLongLine(&command, &commandSize);
                if (strcmp(command, "QUIT")==0) {
                    #if DEBUG >= 1
                    printf("DEUBG: Sending SIGTERM to child.\n");
                    #endif

                    // Send SIGTERM to tell serialIO child to exit
                    kill(serialIOPid, SIGTERM);
                    // Send SIGTERM to tell uInput child to exit
                    kill(uInputPid, SIGTERM);
                    // Wait for all children to exit
                    while (wait(NULL) > 0);
                    break;
                }
                free(command);
            }
        }
        break;
    }

	return 0;
}

